#include "Equalizer.h"

Equalizer::Equalizer()
{
	memset(m_gain, 0, sizeof(int)*EQ_LEN);
	m_calc_finished = 0;
	filterInit();
}

Equalizer::~Equalizer()
{
	
}

void Equalizer::setGain(unsigned int freq, unsigned int gain)
{
	switch (freq)
	{
	case 100:
		m_gain[0] = gain;
		break;
	case 200:
		m_gain[1] = gain;
		break;
	case 500:
		m_gain[2] = gain;
		break;
	case 1000:
		m_gain[3] = gain;
		break;
	case 2000:
		m_gain[4] = gain;
		break;
	case 4000:
		m_gain[5] = gain;
		break;
	case 8000:
		m_gain[6] = gain;
		break;
	case 10000:
		m_gain[7] = gain;
		break;
	default:
		break;
	}
	
}

std::vector<float> Equalizer::EqProcess(std::vector<float> &data)
{
	std::vector<float> out(data.size(), 0);
	//std::vector<float> y;
	//float gain = 1.0;
	//float max_pts = 0;
	//float min_pts = 0;
	//m_calc_finished = 0;
	//int waitCount = 0;
	//for (size_t i = 0; i < EQ_LEN; i++)
	//{
	//	/*if (m_gain[i] == 0)
	//	{
	//		m_calc_data[i].resize(data.size(), 0);
	//		std::copy(data.begin(), data.end(), m_calc_data[i].begin());
	//		continue;
	//	}*/
	//	waitCount++;
	//	m_work_thread[i] = std::thread(std::bind(&Equalizer::calcFilterResult, this, data, i));
	//	m_work_thread[i].detach();
	//	/*y = m_filter[i].FilterProcess(data);
	//	for (size_t j = 0; j < y.size(); j++)
	//	{
	//		gain = pow(10, m_gain[i] / 20.0);
	//		y[j] *= gain;
	//		if (y[j] > max_pts)
	//			max_pts = y[j];
	//		if (y[j] < min_pts)
	//			min_pts = y[j];
	//	}
	//	if (max_pts - min_pts > 2.0)
	//	{
	//		float tmp = max_pts - min_pts;
	//		for (size_t j = 0; j < y.size(); j++)
	//		{
	//			y[j] /= tmp;
	//			out[j] += y[j] / EQ_LEN;
	//		}

	//	}
	//	else
	//	{
	//		for (size_t j = 0; j < y.size(); j++)
	//		{
	//			out[j] += y[j] / EQ_LEN;
	//		}
	//	}
	//	max_pts = 0;
	//	min_pts = 0;*/
	//}
	//while (m_calc_finished < waitCount)
	//{
	//	std::this_thread::sleep_for(std::chrono::milliseconds(1));
	//}
	//
	//for (size_t j = 0; j < m_calc_data[0].size(); j++)
	//{
	//	for (size_t k = 0; k < EQ_LEN; k++)
	//	{
	//		out[j] += m_calc_data[k][j]/ EQ_LEN;
	//	}
	//}
	out = m_eq.run(data);
	return out;
}

void Equalizer::calcFilterResult(std::vector<float> &data, unsigned int count)
{
	float gain = 1.0;
	float max_pts = 0;
	float min_pts = 0;
	gain = pow(10, m_gain[count] / 20.0);
	m_calc_data[count] = m_filter[count].FilterProcess(data);
	for (size_t j = 0; j < m_calc_data[count].size(); j++)
	{
		m_calc_data[count][j] *= gain;
		if (m_calc_data[count][j] > max_pts)
			max_pts = m_calc_data[count][j];
		if (m_calc_data[count][j] < min_pts)
			min_pts = m_calc_data[count][j];
	}
	if (max_pts - min_pts > 2.0)
	{
		float tmp = max_pts - min_pts;
		for (size_t j = 0; j < m_calc_data[count].size(); j++)
		{
			m_calc_data[count][j] /= tmp;
		}
	}
	m_calc_mutex.lock();
	m_calc_finished++;
	m_calc_mutex.unlock();
}

void Equalizer::filterInit()
{
	//<31hz
	m_filter[0].SetFilterType(FILTERTYPE::FIR);
	m_filter[0].SetPassType(PASSTYPE::LOWPASS);
	m_filter[0].SetWindowType(WINDOWTYPE::HAMMING);
	m_filter[0].SetFilterArg(100, 100, 48000);
	m_filter[0].SetWindowSize(63);

	//63hz,use 100-300hz band pass
	m_filter[1].SetFilterType(FILTERTYPE::FIR);
	m_filter[1].SetPassType(PASSTYPE::BANDPASS);
	m_filter[1].SetWindowType(WINDOWTYPE::HAMMING);
	m_filter[1].SetFilterArg(100, 300, 48000);
	m_filter[1].SetWindowSize(63);

	//125hz use 400-600 band pass
	m_filter[2].SetFilterType(FILTERTYPE::FIR);
	m_filter[2].SetPassType(PASSTYPE::BANDPASS);
	m_filter[2].SetWindowType(WINDOWTYPE::HAMMING);
	m_filter[2].SetFilterArg(400, 600, 48000);
	m_filter[2].SetWindowSize(63);

	//250hz use 800-1200 band pass
	m_filter[3].SetFilterType(FILTERTYPE::FIR);
	m_filter[3].SetPassType(PASSTYPE::BANDPASS);
	m_filter[3].SetWindowType(WINDOWTYPE::HAMMING);
	m_filter[3].SetFilterArg(800, 1200, 48000);
	m_filter[3].SetWindowSize(63);

	//2khz use 1.6k-2.4k band pass
	m_filter[4].SetFilterType(FILTERTYPE::FIR);
	m_filter[4].SetPassType(PASSTYPE::BANDPASS);
	m_filter[4].SetWindowType(WINDOWTYPE::HAMMING);
	m_filter[4].SetFilterArg(1600, 2400, 48000);
	m_filter[4].SetWindowSize(63);

	//4k use 3.6k-4.4k band pass
	m_filter[5].SetFilterType(FILTERTYPE::FIR);
	m_filter[5].SetPassType(PASSTYPE::BANDPASS);
	m_filter[5].SetWindowType(WINDOWTYPE::HAMMING);
	m_filter[5].SetFilterArg(3600, 4400, 48000);
	m_filter[5].SetWindowSize(63);

	//8k use 7.6k-8.4k band pass
	m_filter[6].SetFilterType(FILTERTYPE::FIR);
	m_filter[6].SetPassType(PASSTYPE::BANDPASS);
	m_filter[6].SetWindowType(WINDOWTYPE::HAMMING);
	m_filter[6].SetFilterArg(7600, 8400, 48000);
	m_filter[6].SetWindowSize(63);

	//>10k use 400-600 band pass
	m_filter[7].SetFilterType(FILTERTYPE::FIR);
	m_filter[7].SetPassType(PASSTYPE::HIGHPASS);
	m_filter[7].SetWindowType(WINDOWTYPE::HAMMING);
	m_filter[7].SetFilterArg(10000, 10000, 48000);
	m_filter[7].SetWindowSize(63);
	
	std::vector<double> gain{ 2, 2, -60, 2, 2, 2, 2, 2 };
	std::vector<double> Q{ 1.5, 1.5, 5, 1.5, 1.5, 1.5, 1.5, 1.5 };
	std::vector<double> f0{100, 200, 500, 1000, 2000, 4000, 8000, 10000};
	m_eq.setEQArgs(f0.data(), gain.data(), Q.data(), 48000);
}
